package org.amse.tanks.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import org.amse.tanks.objects.*;

public class Model implements ModelConstants, Serializable {
    private Map myMap;
    private ArrayList myTanksList;
    private ArrayList myShotsList;
    private ArrayList myBonusesList;
    private ArrayList myExplosionsList;

    public Model() {
        myMap = new Map();
        myTanksList = new ArrayList();
        myShotsList = new ArrayList();
        myBonusesList = new ArrayList();
        myExplosionsList = new ArrayList();
    }

    public synchronized ArrayList getExplosionsList() {
        return (ArrayList) myExplosionsList.clone();
    }

    public synchronized ArrayList getTanksList() {
        return (ArrayList) myTanksList.clone();
    }

    public synchronized ArrayList getShotsList() {
        return (ArrayList) myShotsList.clone();
    }

    public synchronized ArrayList getBonusesList() {
        return (ArrayList) myBonusesList.clone();
    }

    public synchronized void tick() {
        moveTanks();
        makeShots();
        explosionsHandling();
        bonusesHandling();
        shotsHandling();
    }

    private void moveTanks() {
        Iterator iterator = myTanksList.iterator();
        while (iterator.hasNext()) {
            Tank tank = (Tank) iterator.next();
            boolean isIce = false;

            if (tank.getMovingAbilityCounter() >= TANK_MOVING_ABILITY_THRESHOLD) {
                if (tank.getNextDirection() != tank.getDirection()) {
                    tank.setDirection(tank.getNextDirection());
                } else {
                    if (isNextTankPositionValid(tank)) {
                        switch (tank.getDirection()) {
                            case UP:
                                tank.moveUp();
                                break;

                            case LEFT:
                                tank.moveLeft();
                                break;

                            case RIGHT:
                                tank.moveRight();
                                break;

                            case DOWN:
                                tank.moveDown();
                                break;
                        }

                    //sliding on ice handling
                        isIce = true;
                        endLoop: for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                            for (int j = 0; j < MAP_COMPLEX_OBJECT_SIZE; j++) {
                                if (getMapValue(tank.getX() + i, tank.getY() + j) != MAP_ICE) {
                                    isIce = false;
                                    break endLoop;
                                }
                            }
                        }
                        if (isIce && tank.isSliding()) {
                            tank.setSlidingCounter(TANK_SLIDING_STEPS);
                            tank.setSliding(false);
                        }
                    }
                }
                tank.setMovingAbilityCounter(0);
                if (tank.getSlidingCounter() > 0 && isIce) {
                    moveTank(tank.getId(), tank.getDirection());
                    tank.setSlidingCounter(tank.getSlidingCounter() - 1);
                } else {
                    tank.setSliding(true);
                    tank.setSlidingCounter(0);
                }
            } else {
                if (tank.getMovingAbilityCounter() > 0) {
                    tank.setMovingAbilityCounter(tank.getMovingAbilityCounter() + 1);
                }
            }
        }
    }

    private void makeShots() {
        Iterator iterator = myTanksList.iterator();
        while (iterator.hasNext()) {
            Tank tank = (Tank) iterator.next();
            int x = 0;
            int y = 0;
            Direction direction = Direction.UP;

            if (tank.isShotMade() && tank.getShotsInabilityCounter() <= 0) {
                switch (tank.getDirection()) {
                    case UP:
                        x = tank.getX() + MAP_COMPLEX_OBJECT_SIZE/2 - 1 + MAP_COMPLEX_OBJECT_SIZE%2;
                        y = tank.getY();
                        direction = Direction.UP;
                        break;

                    case LEFT:
                        x = tank.getX();
                        y = tank.getY() + MAP_COMPLEX_OBJECT_SIZE/2 - 1 + MAP_COMPLEX_OBJECT_SIZE%2;
                        direction = Direction.LEFT;
                        break;

                    case RIGHT:
                        x = tank.getX() + MAP_COMPLEX_OBJECT_SIZE - 1;
                        y = tank.getY() + MAP_COMPLEX_OBJECT_SIZE/2 - 1 + MAP_COMPLEX_OBJECT_SIZE%2;
                        direction = Direction.RIGHT;
                        break;

                    case DOWN:
                        direction = Direction.DOWN;
                        x = tank.getX() + MAP_COMPLEX_OBJECT_SIZE/2 - 1 + MAP_COMPLEX_OBJECT_SIZE%2;
                        y = tank.getY() + MAP_COMPLEX_OBJECT_SIZE - 1;
                        break;
                }
                myShotsList.add(new Shot(x, y, direction, tank.getId(), tank.isPiercingBonusTaken()));

                if (tank.isRateOfFireBonusTaken()) {
                    tank.setShotsInabilityCounter(TANK_INABILITY_OF_FIRE_WITH_HIGH_RATE);
                } else {
                    tank.setShotsInabilityCounter(TANK_INABILITY_OF_FIRE_WITH_DEFAULT_RATE);
                }
            } else {
                tank.setShotsInabilityCounter(tank.getShotsInabilityCounter() - 1);
            }
            tank.setShotMade(false);
        }
    }

    private void explosionsHandling() {
        Iterator iterator = myExplosionsList.iterator();
        while (iterator.hasNext()) {
            Explosion explosion = (Explosion) iterator.next();

            explosion.TtlDown();
            if (explosion.getTtl() < 0) {
                iterator.remove();
            }
        }
    }

    private void bonusesHandling() {
        Random randomGenerator = new Random();
        if (randomGenerator.nextInt(BONUS_APPEARANCE_PROBABILITY) == 0) {
            addBonus();
        }

        Iterator iteratorBonuses = myBonusesList.iterator();
        Iterator iteratorTanks;
        Tank tank;
        int tankX;
        int tankY;
        Bonus bonus;
        int bonusX;
        int bonusY;
        while (iteratorBonuses.hasNext()) {
            bonus = (Bonus) iteratorBonuses.next();

            bonusX = bonus.getX();
            bonusY = bonus.getY();

        //check timing
            bonus.ttlDown();
            if (bonus.getTtl() < 0) {
                iteratorBonuses.remove();
                continue;
            }

        //check taking
            iteratorTanks = myTanksList.iterator();
            while (iteratorTanks.hasNext()) {
                tank = (Tank) iteratorTanks.next();

                tankX = tank.getX();
                tankY = tank.getY();

                if (tankX - MAP_COMPLEX_OBJECT_SIZE < bonusX &&
                        bonusX < tankX + MAP_COMPLEX_OBJECT_SIZE &&
                        tankY - MAP_COMPLEX_OBJECT_SIZE < bonusY &&
                        bonusY < tankY + MAP_COMPLEX_OBJECT_SIZE) {
                    //tank handling
                    switch (bonus.getValue()) {
                        case BONUS_SHOT:
                            tank.setRateOfFireBonusTaken(true);
                            break;

                        case BONUS_FAST:
                            tank.setSpeedBonusTaken(true);
                            break;

                        case BONUS_POWER:
                            tank.setPiercingBonusTaken(true);
                            break;
                    }
                    iteratorBonuses.remove();
                    break;
                }
            }
        }
    }

    private void shotsHandling() {
        Iterator iteratorShots = myShotsList.iterator();
        Iterator iteratorTanks;
        Tank tank;
        int tankX;
        int tankY;
        Shot shot;
        Direction shotDirection;
        int shotX;
        int shotY;

        while (iteratorShots.hasNext()) {
            shot = (Shot) iteratorShots.next();

            shotDirection = shot.getDirection();
            shotX = shot.getX();
            shotY = shot.getY();

        //shots moving:
            boolean isShotOut = false;
            switch (shotDirection) {
                case UP:
                    if (shotY > 0) {
                        shot.setY(shotY - 1);
                    } else {
                        isShotOut = true;
                    }
                    break;

                case DOWN:
                    if (shotY < myMap.getHeight() - 1) {
                        shot.setY(shotY + 1);
                    } else {
                        isShotOut = true;
                    }
                    break;

                case LEFT:
                    if (shotX > 0) {
                        shot.setX(shotX - 1);
                    } else {
                        isShotOut = true;
                    }
                    break;

                case RIGHT:
                    if (shotX < myMap.getWidth() - 1) {
                        shot.setX(shotX + 1);
                    } else {
                        isShotOut = true;
                    }
                    break;
            }
            if (isShotOut) {
                myExplosionsList.add(new Explosion(shotX - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                    shotY - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                    false, EXPLOSION_EXISTENCE_TICKS));
                iteratorShots.remove();
                continue;
            }
            shotX = shot.getX();
            shotY = shot.getY();


//need change
        //check hits in wall
//            if (myMap.getValue(shotX, shotY) == MAP_BRICK ||
//                    myMap.getValue(shotX, shotY) == MAP_CONCRETE) {
//
//            } else {
//                if (MAP_COMPLEX_OBJECT_SIZE%2 == 0) {
//                    if (myMap.getValue(shotX + 1, shotY) == MAP_BRICK ||
//                            myMap.getValue(shotX, shotY) == MAP_CONCRETE) {
//
//                    }
//                    if (myMap.getValue(shotX, shotY + 1) == MAP_BRICK ||
//                            myMap.getValue(shotX, shotY) == MAP_CONCRETE) {
//
//                    }
//                }
//            }
//
//            int[][] firstLayer = new int[MAP_COMPLEX_OBJECT_SIZE][2];
//            int[][] firstSecond = new int[MAP_COMPLEX_OBJECT_SIZE][2];
//
//            switch (shotDirection) {
//                case UP:
//                    if (myMap.getValue(shotX, shotY) == MAP_BRICK ||
//                            myMap.getValue(shotX, shotY) == MAP_CONCRETE ||
//                            (MAP_COMPLEX_OBJECT_SIZE%2 == 0) &&
//                            (myMap.getValue(shotX + 1, shotY) == MAP_BRICK ||
//                            myMap.getValue(shotX, shotY) == MAP_CONCRETE)) {
//
//
//                    }
//
//                    break;
//
//                case DOWN:
//                    break;
//
//                case LEFT:
//                    break;
//
//                case RIGHT:
//                    break;
//            }
//
//            boolean isSecondLayerDestroyed = false;
//            for (int i = MAP_COMPLEX_OBJECT_SIZE/2; i > 0; i--) {
//
//            }
//            for (int i = MAP_COMPLEX_OBJECT_SIZE/2; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
//
//            }
//
//
//            for (int i = 0; i < 2; i++) {
//                for (int j = 0; j < MAP_COMPLEX_OBJECT_SIZE; j++) {
//
//                }
//            }
            //////////////////////

            shotX = shot.getX();
            shotY = shot.getY();
            if (shot.isPiercing()) {
                if (myMap.getValue(shotX, shotY) == MAP_CONCRETE) {
                    myMap.setValue(shotX, shotY, MAP_FLOOR);

                    if (shotDirection == Direction.UP || shotDirection == Direction.DOWN) {
                        if (myMap.getValue(shotX - 1, shotY) == MAP_BRICK ||
                                myMap.getValue(shotX - 1, shotY) == MAP_CONCRETE) {
                            myMap.setValue(shotX - 1, shotY, MAP_FLOOR);
                        }
                        if (myMap.getValue(shotX + 1, shotY) == MAP_BRICK ||
                                myMap.getValue(shotX + 1, shotY) == MAP_CONCRETE) {
                            myMap.setValue(shotX + 1, shotY, MAP_FLOOR);
                        }
                    } else {
                        if (shotDirection == Direction.LEFT || shotDirection == Direction.RIGHT) {
                            if (myMap.getValue(shotX, shotY - 1) == MAP_BRICK ||
                                    myMap.getValue(shotX, shotY - 1) == MAP_CONCRETE) {
                                myMap.setValue(shotX, shotY - 1, MAP_FLOOR);
                            }
                            if (myMap.getValue(shotX, shotY + 1) == MAP_BRICK ||
                                    myMap.getValue(shotX, shotY + 1) == MAP_CONCRETE) {
                                myMap.setValue(shotX, shotY + 1, MAP_FLOOR);
                            }
                        }
                    }

                    myExplosionsList.add(new Explosion(shotX - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                        shotY - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                        false, EXPLOSION_EXISTENCE_TICKS));
                    iteratorShots.remove();
                    continue;
                } else {
                    if (myMap.getValue(shotX, shotY) == MAP_BRICK) {
                        myMap.setValue(shotX, shotY, MAP_FLOOR);

                        if (shotDirection == Direction.UP || shotDirection == Direction.DOWN) {
                            if (myMap.getValue(shotX - 1, shotY) == MAP_BRICK ||
                                    myMap.getValue(shotX - 1, shotY) == MAP_CONCRETE) {
                                myMap.setValue(shotX - 1, shotY, MAP_FLOOR);
                            }
                            if (myMap.getValue(shotX + 1, shotY) == MAP_BRICK ||
                                    myMap.getValue(shotX + 1, shotY) == MAP_CONCRETE) {
                                myMap.setValue(shotX + 1, shotY, MAP_FLOOR);
                            }
                            if (shotDirection == Direction.UP) {
                                if (myMap.getValue(shotX, shotY - 1) == MAP_BRICK) {
                                    myMap.setValue(shotX, shotY - 1, MAP_FLOOR);
                                }
                                if (myMap.getValue(shotX - 1, shotY - 1) == MAP_BRICK) {
                                    myMap.setValue(shotX - 1, shotY - 1, MAP_FLOOR);
                                }
                                if (myMap.getValue(shotX + 1, shotY - 1) == MAP_BRICK) {
                                    myMap.setValue(shotX + 1, shotY - 1, MAP_FLOOR);
                                }
                            } else {
                                if (myMap.getValue(shotX, shotY + 1) == MAP_BRICK) {
                                    myMap.setValue(shotX, shotY + 1, MAP_FLOOR);
                                }
                                if (myMap.getValue(shotX - 1, shotY + 1) == MAP_BRICK) {
                                    myMap.setValue(shotX - 1, shotY + 1, MAP_FLOOR);
                                }
                                if (myMap.getValue(shotX + 1, shotY + 1) == MAP_BRICK) {
                                    myMap.setValue(shotX + 1, shotY + 1, MAP_FLOOR);
                                }
                            }
                        } else {
                            if (shotDirection == Direction.LEFT || shotDirection == Direction.RIGHT) {
                                if (myMap.getValue(shotX, shotY - 1) == MAP_BRICK ||
                                        myMap.getValue(shotX, shotY - 1) == MAP_CONCRETE) {
                                    myMap.setValue(shotX, shotY - 1, MAP_FLOOR);
                                }
                                if (myMap.getValue(shotX, shotY + 1) == MAP_BRICK ||
                                        myMap.getValue(shotX, shotY + 1) == MAP_CONCRETE) {
                                    myMap.setValue(shotX, shotY + 1, MAP_FLOOR);
                                }
                                if (shotDirection == Direction.LEFT) {
                                    if (myMap.getValue(shotX - 1, shotY) == MAP_BRICK) {
                                        myMap.setValue(shotX - 1, shotY, MAP_FLOOR);
                                    }
                                    if (myMap.getValue(shotX - 1, shotY - 1) == MAP_BRICK) {
                                        myMap.setValue(shotX - 1, shotY - 1, MAP_FLOOR);
                                    }
                                    if (myMap.getValue(shotX - 1, shotY + 1) == MAP_BRICK) {
                                        myMap.setValue(shotX - 1, shotY + 1, MAP_FLOOR);
                                    }
                                } else {
                                    if (myMap.getValue(shotX + 1, shotY) == MAP_BRICK) {
                                        myMap.setValue(shotX + 1, shotY, MAP_FLOOR);
                                    }
                                    if (myMap.getValue(shotX + 1, shotY - 1) == MAP_BRICK) {
                                        myMap.setValue(shotX + 1, shotY - 1, MAP_FLOOR);
                                    }
                                    if (myMap.getValue(shotX + 1, shotY + 1) == MAP_BRICK) {
                                        myMap.setValue(shotX + 1, shotY + 1, MAP_FLOOR);
                                    }
                                }
                            }
                        }

                        myExplosionsList.add(new Explosion(shotX - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                            shotY - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                            false, EXPLOSION_EXISTENCE_TICKS));
                        iteratorShots.remove();
                        continue;
                    }
                }


            } else {   //shot is not piercing
                if (myMap.getValue(shotX, shotY) == MAP_BRICK) {
                    myMap.setValue(shotX, shotY, MAP_FLOOR);

                    if (shotDirection == Direction.UP || shotDirection == Direction.DOWN) {
                        if (myMap.getValue(shotX - 1, shotY) == MAP_BRICK) {
                            myMap.setValue(shotX - 1, shotY, MAP_FLOOR);
                        }
                        if (myMap.getValue(shotX + 1, shotY) == MAP_BRICK) {
                            myMap.setValue(shotX + 1, shotY, MAP_FLOOR);
                        }
                    } else {
                        if (shotDirection == Direction.LEFT || shotDirection == Direction.RIGHT) {
                            if (myMap.getValue(shotX, shotY - 1) == MAP_BRICK) {
                                myMap.setValue(shotX, shotY - 1, MAP_FLOOR);
                            }
                            if (myMap.getValue(shotX, shotY + 1) == MAP_BRICK) {
                                myMap.setValue(shotX, shotY + 1, MAP_FLOOR);
                            }
                        }
                    }

                    myExplosionsList.add(new Explosion(shotX - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                        shotY - MAP_COMPLEX_OBJECT_SIZE/2 - MAP_COMPLEX_OBJECT_SIZE%2 + 1,
                                                        false, EXPLOSION_EXISTENCE_TICKS));
                    iteratorShots.remove();
                    continue;
                } else {
                    if (myMap.getValue(shotX, shotY) == MAP_CONCRETE) {
                        iteratorShots.remove();
                        continue;
                    }
                }
            }






        //check hits in tanks
            iteratorTanks = myTanksList.iterator();
            while (iteratorTanks.hasNext()) {
                tank = (Tank) iteratorTanks.next();

                tankX = tank.getX();
                tankY = tank.getY();

                boolean isHit = false;

                if (tankX <= shotX &&
                        shotX < tankX + MAP_COMPLEX_OBJECT_SIZE &&
                        tankY <= shotY &&
                        shotY < tankY + MAP_COMPLEX_OBJECT_SIZE) {
                    isHit = true;
                } else {
                    if (MAP_COMPLEX_OBJECT_SIZE%2 == 0) {
                        if (shot.getDirection() == Direction.UP || shot.getDirection() == Direction.DOWN) {
                            if (shotX + 1 == tankX &&
                                    tankY <= shotY &&
                                    shotY < tankY + MAP_COMPLEX_OBJECT_SIZE) {
                                isHit = true;
                            }
                        } else {
                            if (shotY + 1 == tankY &&
                                    tankX <= shotX &&
                                    shotX < tankX + MAP_COMPLEX_OBJECT_SIZE) {
                                isHit = true;
                            }
                        }
                    }
                }

                if (isHit) {
                    //statistics handling

                    myExplosionsList.add(new Explosion(tankX, tankY, true, EXPLOSION_EXISTENCE_TICKS));
                    iteratorShots.remove();
                    iteratorTanks.remove();
                    break;
                }
            }
        }
    }

    public void TankMakeShot(int id) {
        Tank tank = getTank(id);
        if (tank == null) {
            return;
        }

        tank.setShotMade(true);
    }

    public void addTank(Tank tank) {
        myTanksList.add(tank);
    }

    private void addBonus() {
        int x, y;
        int value;
        int ttl;

        Random randomGenerator = new Random();
        x = randomGenerator.nextInt(myMap.getWidth() - (MAP_COMPLEX_OBJECT_SIZE - 1));
        y = randomGenerator.nextInt(myMap.getHeight() - (MAP_COMPLEX_OBJECT_SIZE - 1));
        value = randomGenerator.nextInt(3) + BONUS_SHOT;
        ttl = BONUS_EXISTENCE_TICKS;

        myBonusesList.add(new Bonus(x, y, value, ttl));
    }

    private Tank getTank(int id) {
        Iterator iterator = myTanksList.iterator();
        while (iterator.hasNext()) {
            Tank tank = (Tank) iterator.next();
            if (tank.getId() == id) {
                return tank;
            }
        }
        return null;
    }

//Map geometry:
    public int getMapWidth() {
        return myMap.getWidth();
    }

    public int getMapHeight() {
        return myMap.getHeight();
    }

    public int getMapValue(int x, int y) {
        return myMap.getValue(x, y);
    }

    public void setMapSize(int width, int height) {
        myMap.setSize(width, height);
    }

    public void setMapValue(int x, int y, int value) {
        myMap.setValue(x, y, value);
    }

    public void moveTank(int id, Direction direction) {
        Tank tank = getTank(id);

        if (tank != null) {
            tank.setNextDirection(direction);

            if (tank.isSpeedBonusTaken()) {
                if (tank.getMovingAbilityCounter() < TANK_MOVING_ABILITY_FAST) {
                    tank.setMovingAbilityCounter(TANK_MOVING_ABILITY_FAST);
                }
            } else {
                if (tank.getMovingAbilityCounter() < TANK_MOVING_ABILITY_DEFAULT) {
                    tank.setMovingAbilityCounter(TANK_MOVING_ABILITY_DEFAULT);
                }
            }
        }
    }

    private boolean isNextTankPositionValid(Tank tank) {
        int tankX = tank.getX();
        int tankY = tank.getY();

        switch (tank.getDirection()) {
            case UP:
                for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                    if (!isPointEmpty(tankX + i, tankY - 1)) {
                        return false;
                    }
                }
                break;

            case LEFT:
                for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                    if (!isPointEmpty(tankX - 1, tankY + i)) {
                        return false;
                    }
                }
                break;

            case RIGHT:
                for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                    if (!isPointEmpty(tankX + MAP_COMPLEX_OBJECT_SIZE, tankY + i)) {
                        return false;
                    }
                }
                break;

            case DOWN:
                for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                    if (!isPointEmpty(tankX + i, tankY + MAP_COMPLEX_OBJECT_SIZE)) {
                        return false;
                    }
                }
                break;
        }
        return true;
    }

    private boolean isPointEmpty(int x, int y) { //point is not wall or tank
        if (!isPointAvailable(x, y)) {
            return false;
        }

        Tank tank;
        int tankX;
        int tankY;
        Iterator iterator = myTanksList.iterator(); //is it tank
        while (iterator.hasNext()) {
            tank = (Tank) iterator.next();
            tankX = tank.getX();
            tankY = tank.getY();

            for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
                for (int j = 0; j < MAP_COMPLEX_OBJECT_SIZE; j++) {
                    if (x == tankX + j && y == tankY + i) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    public boolean isPositionEmptyForTank(int x, int y) {
        for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
            for (int j = 0; j < MAP_COMPLEX_OBJECT_SIZE; j++) {
                if (!isPointEmpty(x + j, y + i)) {
                    return false;
                }
            }
        }
        return true;
    }

    public boolean isPositionAvailableForTank(int x, int y) {
        for (int i = 0; i < MAP_COMPLEX_OBJECT_SIZE; i++) {
            for (int j = 0; j < MAP_COMPLEX_OBJECT_SIZE; j++) {
                if (!isPointAvailable(x + j, y + i)) {
                    return false;
                }
            }
        }
        return true;
    }

    private boolean isPointAvailable(int x, int y) { //point is not wall, but may be tank
        if (x < 0 ||                            //is out of map
                x > myMap.getWidth() - 1 ||
                y < 0 ||
                y > myMap.getHeight() - 1) {
            return false;
        }

        if (myMap.getValue(x, y) == MAP_BRICK ||
                myMap.getValue(x, y) == MAP_CONCRETE ||
                myMap.getValue(x, y) == MAP_WATER) {
            return false;
        }

        return true;
    }

    public boolean isOver() {
        if (myTanksList.size() == 0) {
            return true;
        }
        return false;
    }

    public Tank getPositionedTank() {
        Tank tank = new Tank();
        tank.setDirection(Direction.DOWN);

        int finalX;
        int finalY;
        Random randomGenerator = new Random();
        do {
            finalX = randomGenerator.nextInt(getMapWidth());
            finalY = randomGenerator.nextInt(getMapHeight());
        } while (!isPositionEmptyForTank(finalX, finalY));
        tank.setX(finalX);
        tank.setY(finalY);

        return tank;
    }
}
